package org.Yiran.timetale_re.util.physics;

import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.world.entity.vehicle.Minecart;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.decoration.Painting;
import net.minecraft.world.entity.projectile.Projectile;

/**
 * 实体质量计算器
 * <p>
 * 根据实体的碰撞箱大小和其他属性计算实体的质量，支持多种实体类型的物理属性计算。
 * 提供质量、体积、密度、阻力系数等物理参数的计算功能。
 * </p>
 * 
 * @author Yiran
 * @version 1.0
 */
public class EntityMassCalculator {
    
    // ================================
    // 密度常量定义
    // ================================
    
    /**
     * 玩家密度值 (kg/m³)
     * 人体密度约等于水的密度
     */
    private static final double PLAYER_DENSITY = 1000.0;
    
    /**
     * 物品密度值 (kg/m³)
     * 假设物品主要由金属或石头制成
     */
    private static final double ITEM_DENSITY = 2000.0;
    
    /**
     * 生物密度值 (kg/m³)
     * 普通生物的平均密度
     */
    private static final double LIVING_ENTITY_DENSITY = 950.0;
    
    /**
     * 船只密度值 (kg/m³)
     * 假设船只主要由木材构成
     */
    private static final double BOAT_DENSITY = 500.0;
    
    /**
     * 矿车密度值 (kg/m³)
     * 假设矿车由钢铁制成
     */
    private static final double MINECART_DENSITY = 7800.0;
    
    /**
     * 物品展示框密度值 (kg/m³)
     * 展示框本身材质较轻
     */
    private static final double ITEM_FRAME_DENSITY = 300.0;
    
    /**
     * 画密度值 (kg/m³)
     * 画作本身的重量很轻
     */
    private static final double PAINTING_DENSITY = 100.0;
    
    /**
     * 投射物密度值 (kg/m³)
     * 如箭矢等投射物，通常由金属制成
     */
    private static final double PROJECTILE_DENSITY = 2500.0;
    
    /**
     * 默认密度值 (kg/m³)
     * 当无法确定实体类型时使用的默认密度
     */
    private static final double DEFAULT_DENSITY = 1000.0;
    
    // ================================
    // 特殊实体质量常量
    // ================================
    
    /**
     * 玩家基础质量 (kg)
     * 成年人平均体重约为70公斤
     */
    private static final double PLAYER_BASE_MASS = 70.0;
    
    /**
     * 物品展示框质量 (kg)
     * 展示框本身的质量
     */
    private static final double ITEM_FRAME_MASS = 0.5;
    
    /**
     * 画的质量 (kg)
     * 画作本身的质量
     */
    private static final double PAINTING_MASS = 0.3;
    
    // ================================
    // 实体质量计算方法
    // ================================
    
    /**
     * 计算实体的质量
     * <p>
     * 根据实体类型采用不同策略计算质量:
     * 1. 对于特殊实体(如玩家、物品展示框、画)使用预定义质量值
     * 2. 对于普通实体使用体积×密度的方式计算质量
     * </p>
     * 
     * @param entity 待计算质量的实体对象，不能为空
     * @return 实体的质量，单位为千克(kg)，值大于0
     */
    public static double calculateEntityMass(Entity entity) {
        // 特殊处理某些实体类型
        if (entity instanceof Player) {
            return calculatePlayerMass((Player) entity);
        } else if (entity instanceof ItemFrame) {
            return ITEM_FRAME_MASS;
        } else if (entity instanceof Painting) {
            return PAINTING_MASS;
        }
        
        // 获取实体的碰撞箱体积
        double volume = calculateEntityVolume(entity);
        
        // 获取实体的密度
        double density = getEntityDensity(entity);
        
        // 质量 = 体积 × 密度
        return volume * density;
    }
    
    // ================================
    // 玩家质量计算方法
    // ================================
    
    /**
     * 计算玩家的质量
     * <p>
     * 使用固定的PLAYER_BASE_MASS作为玩家质量，不考虑装备等因素
     * </p>
     * 
     * @param player 玩家对象，不能为空
     * @return 玩家质量，单位为千克(kg)
     */
    private static double calculatePlayerMass(Player player) {
        return PLAYER_BASE_MASS;
    }
    
    // ================================
    // 实体体积计算方法
    // ================================
    
    /**
     * 计算实体的体积（基于碰撞箱）
     * <p>
     * 通过实体的边界框(BoundingBox)尺寸计算体积，假设实体为长方体形状，
     * 并应用填充系数以更贴近实际情形
     * </p>
     * 
     * @param entity 实体对象，不能为空
     * @return 实体体积，单位为立方米(m³)，值大于等于0
     */
    public static double calculateEntityVolume(Entity entity) {
        // 获取实体的碰撞箱尺寸
        double width = entity.getBbWidth();
        double height = entity.getBbHeight();
        double depth = entity.getBbWidth(); // 假设深度等于宽度
        
        // 计算长方体体积
        double volume = width * height * depth;
        
        // 转换为立方米（Minecraft中1个方块=1m³）
        // 但考虑到实体通常不会完全填满方块空间，乘以一个系数
        return volume * 0.7; // 70%的填充系数
    }
    
    // ================================
    // 实体密度获取方法
    // ================================
    
    /**
     * 获取实体的密度
     * <p>
     * 根据实体的具体类型返回对应的密度值，对于未知类型的实体，
     * 尝试通过实体名称进行推断
     * </p>
     * 
     * @param entity 实体对象，不能为空
     * @return 实体密度，单位为千克每立方米(kg/m³)，值大于0
     */
    public static double getEntityDensity(Entity entity) {
        if (entity instanceof Player) {
            return PLAYER_DENSITY;
        } else if (entity instanceof ItemEntity) {
            return ITEM_DENSITY;
        } else if (entity instanceof LivingEntity) {
            return LIVING_ENTITY_DENSITY;
        } else if (entity instanceof Boat) {
            return BOAT_DENSITY;
        } else if (entity instanceof Minecart) {
            return MINECART_DENSITY;
        } else if (entity instanceof ItemFrame) {
            return ITEM_FRAME_DENSITY;
        } else if (entity instanceof Painting) {
            return PAINTING_DENSITY;
        } else if (entity instanceof Projectile) {
            return PROJECTILE_DENSITY;
        } else {
            // 对于其他实体，尝试根据实体名称进行判断
            return estimateDensityByEntityName(entity);
        }
    }
    
    // ================================
    // 实体名称密度估算方法
    // ================================
    
    /**
     * 根据实体名称估计密度
     * <p>
     * 当无法通过instanceof准确判断实体类型时，通过分析实体类名中的关键词
     * 来推测实体的大致密度
     * </p>
     * 
     * @param entity 实体对象，不能为空
     * @return 估计的密度值，单位为千克每立方米(kg/m³)，值大于0
     */
    private static double estimateDensityByEntityName(Entity entity) {
        String entityName = entity.getClass().getSimpleName().toLowerCase();
        
        if (entityName.contains("item") || entityName.contains("drop")) {
            return ITEM_DENSITY;
        } else if (entityName.contains("mob") || entityName.contains("animal") || entityName.contains("monster")) {
            return LIVING_ENTITY_DENSITY;
        } else if (entityName.contains("boat")) {
            return BOAT_DENSITY;
        } else if (entityName.contains("minecart")) {
            return MINECART_DENSITY;
        } else if (entityName.contains("arrow") || entityName.contains("projectile")) {
            return PROJECTILE_DENSITY;
        } else {
            return DEFAULT_DENSITY;
        }
    }
    
    // ================================
    // 实体集合总质量计算方法
    // ================================
    
    /**
     * 计算实体集合的总质量
     * <p>
     * 遍历实体集合并累加每个实体的质量得到总质量
     * </p>
     * 
     * @param entities 实体集合，不能为空
     * @return 所有实体的总质量，单位为千克(kg)，值大于等于0
     */
    public static double calculateTotalMass(Iterable<Entity> entities) {
        double totalMass = 0.0;
        for (Entity entity : entities) {
            totalMass += calculateEntityMass(entity);
        }
        return totalMass;
    }
    
    // ================================
    // 实体阻力系数获取方法
    // ================================
    
    /**
     * 根据质量获取实体的阻力系数
     * <p>
     * 阻力系数用于计算空气阻力等物理效应，质量越大通常阻力系数也越大
     * </p>
     * 
     * @param entity 实体对象，不能为空
     * @return 阻力系数，无单位，值大于0
     */
    public static double getDragCoefficient(Entity entity) {
        double mass = calculateEntityMass(entity);
        
        // 质量越大的实体，相对阻力系数越小
        // 这是一个简化的模型
        if (mass < 1.0) {
            return 0.47; // 小物体（类似球体）
        } else if (mass < 10.0) {
            return 1.0;  // 中等物体
        } else if (mass < 100.0) {
            return 1.4;  // 大物体
        } else {
            return 2.0;  // 很大物体
        }
    }
    
    // ================================
    // 实体横截面积计算方法
    // ================================
    
    /**
     * 计算实体的横截面积（用于风阻计算）
     * <p>
     * 横截面积是计算空气阻力的重要参数，这里简化为圆柱体的正面投影面积
     * </p>
     * 
     * @param entity 实体对象，不能为空
     * @return 横截面积，单位为平方米(m²)，值大于等于0
     */
    public static double calculateCrossSectionalArea(Entity entity) {
        double width = entity.getBbWidth();
        double height = entity.getBbHeight();
        
        // 简化为圆柱体的正面投影面积
        return Math.PI * (width/2) * (width/2);
    }
    
    // ================================
    // 实体形状系数获取方法
    // ================================
    
    /**
     * 获取实体的形状系数（用于更精确的物理计算）
     * <p>
     * 不同形状的实体具有不同的空气动力学特性，用形状系数来表示这种差异
     * </p>
     * 
     * @param entity 实体对象，不能为空
     * @return 形状系数，无单位，值大于0
     */
    public static double getShapeFactor(Entity entity) {
        if (entity instanceof Player) {
            return 0.7; // 玩家站立时的形状系数
        } else if (entity instanceof ItemEntity) {
            return 0.47; // 球形物品
        } else if (entity instanceof LivingEntity) {
            return 0.8; // 生物形状
        } else {
            return 1.0; // 默认形状系数
        }
    }
}